﻿using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using com.kmer;

namespace kmer.Helper {
	public static class XmlHelper {
		/// <summary>
		/// Gets the value of the specified XmlNode.
		/// </summary>
		public static string GetValue(XmlNode node) {
			if (node != null && node.FirstChild != null) return node.FirstChild.Value;
			else return null;
		}

		/// <summary>
		/// Gets the specified attribute from the specified XmlNode.
		/// </summary>
		public static string GetAttribute(XmlNode node, string attName, string pDefaultValue) {
			if (node != null && node.Attributes !=null && node.Attributes[attName] != null)
				return node.Attributes[attName].Value;
			else return pDefaultValue;
		}

		/// <summary>
		/// Checks that if the XmlNode has a value.
		/// </summary>
		public static bool HasValue(XmlNode node) {
			return (node != null && node.FirstChild != null && node.FirstChild.Value != null);
		}

		/// <summary>
		/// Checks if the XmlNode has the specified attribute.
		/// </summary>
		public static bool HasAttribute(XmlNode node, string attName) {
			return (node != null && node.Attributes!=null && node.Attributes[attName] != null);
		}

		/// <summary>
		/// Reads a xml file and returns it as a XmlNode. Returns null on failure.
		/// </summary>
		public static XmlNode LoadXmlDocument(string file) {
			try {
				var document = new XmlDocument {PreserveWhitespace = false};
				document.Load(file);
				try {
					var declNode = document.FirstChild;
					var rootNode = declNode.NextSibling;
					return rootNode;
					//} catch (Exception ex1) {
				} catch {
					//ErrorManager.ShowError(ex1);
					return null;
				}
				//} catch (Exception ex2) {
			} catch {
				//ErrorManager.ShowError(ex2);
				return null;
			}
		}
		public static XmlDocument Create(string pRootName) {
			var doc = new XmlDocument();
			var el = doc.CreateElement(pRootName);
			doc.AppendChild(el);
			return doc;
		}
		public static XmlElement AppendChildToRoot(this XmlDocument doc, XmlElement elToAdd) {
			doc.FirstChild.AppendChild(elToAdd);
			return elToAdd;
		}
		//public static XmlElement CreateElement(this XmlDocument doc, string elementName) {
		//	var el = doc.CreateElement(elementName);
		//	return el;
		//}
		public static XmlElement AddElement(this XmlElement el, string elementName) {
			if (el.OwnerDocument == null) throw new ArgumentException("el.OwnerDocument 不能为空", "el");
			elementName = ReplaceHexadecimalSymbols(elementName);
			if (string.IsNullOrWhiteSpace(elementName)) throw new ArgumentException("elementName 不能为空", "elementName");
			var doc = el.OwnerDocument;
			var rel = doc.CreateElement(elementName);
			el.AppendChild(rel);
			return rel;
		}
		public static XmlElement AddAttibute(this XmlElement el, string pAttribName, string pValue) {
			if (el.OwnerDocument == null) throw new ArgumentException("el.OwnerDocument 不能为空", "el");
			pAttribName = ReplaceHexadecimalSymbols(pAttribName);
			if (string.IsNullOrWhiteSpace(pAttribName)) throw new ArgumentException("pAttribName 不能为空", "pAttribName");
			var attr = el.OwnerDocument.CreateAttribute(pAttribName);
			attr.Value = ReplaceHexadecimalSymbols(pValue);
			el.Attributes.Append(attr);
			return el;
		}
		public static XmlElement AddAttibute(this XmlElement el, string pAttribName, object pValue) {
			if (el.OwnerDocument == null) throw new ArgumentException("el.OwnerDocument 不能为空", "el");
			if (pValue == null) throw new ArgumentNullException("pValue");
			pAttribName = ReplaceHexadecimalSymbols(pAttribName);
			if (string.IsNullOrWhiteSpace(pAttribName)) throw new ArgumentException("pAttribName 不能为空", "pAttribName");
			var attr = el.OwnerDocument.CreateAttribute(pAttribName);
			attr.Value = ReplaceHexadecimalSymbols(pValue.ToString());
			el.Attributes.Append(attr);
			return el;
		}
		public static XmlElement AddAttibute<T>(this XmlElement el, string pAttribName, T pValue, string format = "") {
			if (el.OwnerDocument == null) throw new ArgumentException("el.OwnerDocument 不能为空", "el");
			pAttribName = ReplaceHexadecimalSymbols(pAttribName);
			if (string.IsNullOrWhiteSpace(pAttribName)) throw new ArgumentException("pAttribName 不能为空", "pAttribName");
			var attr = el.OwnerDocument.CreateAttribute(pAttribName);
			attr.Value = ReplaceHexadecimalSymbols(
				string.IsNullOrWhiteSpace(format) 
				? pValue.ToString() 
				: string.Format(format, pValue));
			el.Attributes.Append(attr);
			return el;
		}
		public static string GetString(this XmlDocument doc) {
			var sb = new StringBuilder();
			var xs = new XmlWriterSettings {
				Encoding = Encoding.UTF8,
				OmitXmlDeclaration = true,
				WriteEndDocumentOnClose = true,
				//不检查字符
				CheckCharacters = true,
				DoNotEscapeUriAttributes = false
			};
			using (var xw = XmlWriter.Create(sb, xs)) {
				try{
					doc.WriteContentTo(xw);
				} catch (Exception ex){
					Log.Error(ex,"输出XML字串");
					throw;
				}
			}
			return sb.ToString();
		}
		static string ReplaceHexadecimalSymbols(string txt){
			if (string.IsNullOrWhiteSpace(txt)) return string.Empty;
			//const string r = "[\x00-\x08\x0B\x0C\x0E-\x1F\x26]";
			const string r = "[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]";
			return Regex.Replace(txt, r, string.Empty, RegexOptions.Compiled);
		}
	}
}
